import { Op } from 'sequelize';
import { Banner, BannerAttributes } from '../models/Banner';
import { 
  CreateBannerRequest, 
  UpdateBannerRequest, 
  BannerQueryParams, 
  BannerResponse, 
  BannerListResponse,
  BannerStatsResponse,
  PublicBannerResponse,
  PublicBannerListResponse
} from '../types/banner';
import { AppError } from '../utils/errors';
import logger from '../utils/logger';

export class BannerService {
  /**
   * 创建轮播图
   */
  async createBanner(data: CreateBannerRequest): Promise<BannerResponse> {
    try {
      // 验证时间范围
      const startTime = new Date(data.startTime);
      const endTime = new Date(data.endTime);
      
      if (endTime <= startTime) {
        throw new AppError('结束时间必须晚于开始时间', 400);
      }

      const banner = await Banner.create({
        title: data.title,
        image: data.image,
        linkUrl: data.linkUrl,
        sortOrder: data.sortOrder || 0,
        position: data.position || 1,
        startTime,
        endTime,
        status: data.status !== undefined ? data.status : 1,
      });

      logger.info(`轮播图创建成功: ${banner.id}`);
      return this.formatBannerResponse(banner);
    } catch (error) {
      logger.error('创建轮播图失败:', error);
      if (error instanceof AppError) {
        throw error;
      }
      throw new AppError('创建轮播图失败', 500);
    }
  }

  /**
   * 更新轮播图
   */
  async updateBanner(id: number, data: UpdateBannerRequest): Promise<BannerResponse> {
    try {
      const banner = await Banner.findByPk(id);
      if (!banner) {
        throw new AppError('轮播图不存在', 404);
      }

      // 验证时间范围
      if (data.startTime && data.endTime) {
        const startTime = new Date(data.startTime);
        const endTime = new Date(data.endTime);
        
        if (endTime <= startTime) {
          throw new AppError('结束时间必须晚于开始时间', 400);
        }
      }

      const updateData: Partial<BannerAttributes> = {};
      
      if (data.title !== undefined) updateData.title = data.title;
      if (data.image !== undefined) updateData.image = data.image;
      if (data.linkUrl !== undefined) updateData.linkUrl = data.linkUrl;
      if (data.sortOrder !== undefined) updateData.sortOrder = data.sortOrder;
      if (data.position !== undefined) updateData.position = data.position;
      if (data.startTime !== undefined) updateData.startTime = new Date(data.startTime);
      if (data.endTime !== undefined) updateData.endTime = new Date(data.endTime);
      if (data.status !== undefined) updateData.status = data.status;

      await banner.update(updateData);
      await banner.reload();

      logger.info(`轮播图更新成功: ${id}`);
      return this.formatBannerResponse(banner);
    } catch (error) {
      logger.error(`更新轮播图失败 (ID: ${id}):`, error);
      if (error instanceof AppError) {
        throw error;
      }
      throw new AppError('更新轮播图失败', 500);
    }
  }

  /**
   * 删除轮播图
   */
  async deleteBanner(id: number): Promise<void> {
    try {
      const banner = await Banner.findByPk(id);
      if (!banner) {
        throw new AppError('轮播图不存在', 404);
      }

      await banner.destroy();
      logger.info(`轮播图删除成功: ${id}`);
    } catch (error) {
      logger.error(`删除轮播图失败 (ID: ${id}):`, error);
      if (error instanceof AppError) {
        throw error;
      }
      throw new AppError('删除轮播图失败', 500);
    }
  }

  /**
   * 批量删除轮播图
   */
  async deleteBanners(ids: number[]): Promise<void> {
    try {
      const count = await Banner.destroy({
        where: {
          id: {
            [Op.in]: ids,
          },
        },
      });

      if (count === 0) {
        throw new AppError('没有找到要删除的轮播图', 404);
      }

      logger.info(`批量删除轮播图成功: ${ids.join(', ')}`);
    } catch (error) {
      logger.error(`批量删除轮播图失败 (IDs: ${ids.join(', ')}):`, error);
      if (error instanceof AppError) {
        throw error;
      }
      throw new AppError('批量删除轮播图失败', 500);
    }
  }

  /**
   * 获取轮播图详情
   */
  async getBannerById(id: number): Promise<BannerResponse> {
    try {
      const banner = await Banner.findByPk(id);
      if (!banner) {
        throw new AppError('轮播图不存在', 404);
      }

      return this.formatBannerResponse(banner);
    } catch (error) {
      logger.error(`获取轮播图详情失败 (ID: ${id}):`, error);
      if (error instanceof AppError) {
        throw error;
      }
      throw new AppError('获取轮播图详情失败', 500);
    }
  }

  /**
   * 获取轮播图列表
   */
  async getBannerList(params: BannerQueryParams): Promise<BannerListResponse> {
    try {
      const {
        page = 1,
        limit = 10,
        keyword,
        position,
        status,
        startDate,
        endDate,
        sortBy = 'sortOrder',
        sortOrder = 'ASC',
      } = params;

      const offset = (page - 1) * limit;
      const where: any = {};

      // 关键词搜索
      if (keyword) {
        where.title = {
          [Op.like]: `%${keyword}%`,
        };
      }

      // 位置筛选
      if (position !== undefined) {
        where.position = position;
      }

      // 状态筛选
      if (status !== undefined) {
        where.status = status;
      }

      // 时间范围筛选
      if (startDate || endDate) {
        where.createdAt = {};
        if (startDate) {
          where.createdAt[Op.gte] = new Date(startDate);
        }
        if (endDate) {
          where.createdAt[Op.lte] = new Date(endDate);
        }
      }

      const { rows: banners, count: total } = await Banner.findAndCountAll({
        where,
        limit,
        offset,
        order: [[sortBy, sortOrder]],
      });

      const bannerList = banners.map(banner => this.formatBannerResponse(banner));

      return {
        banners: bannerList,
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      };
    } catch (error) {
      logger.error('获取轮播图列表失败:', error);
      throw new AppError('获取轮播图列表失败', 500);
    }
  }

  /**
   * 获取轮播图统计信息
   */
  async getBannerStats(): Promise<BannerStatsResponse> {
    try {
      const now = new Date();
      
      const [
        total,
        active,
        inactive,
        expired,
        upcoming,
        positionStats
      ] = await Promise.all([
        Banner.count(),
        Banner.count({ where: { status: 1 } }),
        Banner.count({ where: { status: 0 } }),
        Banner.count({ 
          where: { 
            status: 1,
            endTime: { [Op.lt]: now }
          } 
        }),
        Banner.count({ 
          where: { 
            status: 1,
            startTime: { [Op.gt]: now }
          } 
        }),
        Banner.findAll({
          attributes: [
            'position',
            [Banner.sequelize!.fn('COUNT', Banner.sequelize!.col('id')), 'count']
          ],
          group: ['position'],
          raw: true
        })
      ]);

      const byPosition: { [key: number]: number } = {};
      positionStats.forEach((stat: any) => {
        byPosition[stat.position] = parseInt(stat.count);
      });

      return {
        total,
        active,
        inactive,
        expired,
        upcoming,
        byPosition,
      };
    } catch (error) {
      logger.error('获取轮播图统计信息失败:', error);
      throw new AppError('获取轮播图统计信息失败', 500);
    }
  }

  /**
   * 获取前端轮播图列表（公开接口）
   */
  async getPublicBanners(position?: 1 | 2): Promise<PublicBannerListResponse> {
    try {
      const now = new Date();
      const where: any = {
        status: 1,
        startTime: { [Op.lte]: now },
        endTime: { [Op.gte]: now },
      };

      if (position !== undefined) {
        where.position = position;
      }

      const banners = await Banner.findAll({
        where,
        order: [['sortOrder', 'ASC'], ['id', 'ASC']],
        attributes: ['id', 'title', 'image', 'linkUrl', 'sortOrder', 'position'],
      });

      const bannerList: PublicBannerResponse[] = banners.map(banner => ({
        id: banner.id,
        title: banner.title,
        image: banner.image,
        linkUrl: banner.linkUrl,
        sortOrder: banner.sortOrder,
        position: banner.position,
      }));

      return {
        banners: bannerList,
        position: position || 1,
      };
    } catch (error) {
      logger.error('获取前端轮播图列表失败:', error);
      throw new AppError('获取前端轮播图列表失败', 500);
    }
  }

  /**
   * 更新轮播图状态
   */
  async updateBannerStatus(id: number, status: 0 | 1): Promise<BannerResponse> {
    try {
      const banner = await Banner.findByPk(id);
      if (!banner) {
        throw new AppError('轮播图不存在', 404);
      }

      await banner.update({ status });
      await banner.reload();

      logger.info(`轮播图状态更新成功: ${id} -> ${status}`);
      return this.formatBannerResponse(banner);
    } catch (error) {
      logger.error(`更新轮播图状态失败 (ID: ${id}):`, error);
      if (error instanceof AppError) {
        throw error;
      }
      throw new AppError('更新轮播图状态失败', 500);
    }
  }

  /**
   * 格式化轮播图响应数据
   */
  private formatBannerResponse(banner: Banner): BannerResponse {
    return {
      id: banner.id,
      title: banner.title,
      image: banner.image,
      linkUrl: banner.linkUrl,
      sortOrder: banner.sortOrder,
      position: banner.position,
      positionText: banner.getPositionText(),
      startTime: banner.startTime.toISOString(),
      endTime: banner.endTime.toISOString(),
      status: banner.status,
      statusText: banner.getStatusText(),
      isActive: banner.isActive(),
      createdAt: banner.createdAt.toISOString(),
      updatedAt: banner.updatedAt.toISOString(),
    };
  }
}

export default new BannerService();